package com.atguigu.gmall.activity.service.impl;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.activity.util.CacheHelper;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.model.activity.OrderRecode;
import com.atguigu.gmall.model.activity.SeckillGoods;
import org.redisson.RedissonLock;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: zm
 * @Date: 2021/8/31 21:02
 */
@Service
public class SeckillGoodsServiceImpl implements SeckillGoodsService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    // 获取所有秒杀商品
    @Override
    public List<SeckillGoods> findAll() {
        return redisTemplate.opsForHash().values(RedisConst.SECKILL_GOODS);
    }

    // 根据skuId获取秒杀商品详情
    @Override
    public SeckillGoods getSeckillGoods(Long skuId) {
//        return (SeckillGoods) redisTemplate.opsForHash().get(RedisConst.SECKILL_GOODS, skuId.toString());

        return (SeckillGoods) redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).get(skuId.toString());
    }

    // 预下单
    @Override
    public void seckillOrder(String userId, Long skuId) {
        // 判断商品的状态位 看是否还有商品
        String status = (String) CacheHelper.get(skuId.toString());
        if (StringUtils.isEmpty(status) || "0".equals(status)) {
            // 已售罄
            return;
        }
        // 判断用户是否是第一次抢购这个商品
        Boolean isExists = redisTemplate.opsForValue().setIfAbsent(RedisConst.SECKILL_USER + userId, skuId, RedisConst.SECKILL__TIMEOUT, TimeUnit.SECONDS);
        if (!isExists) {
            // 表示不是第一抢
            return;
        }
        // 看redis 的list中是否还有数据  进行预减库存
        String result = (String) redisTemplate.opsForList().rightPop(RedisConst.SECKILL_STOCK_PREFIX + skuId);
        if (StringUtils.isEmpty(result)) {
            // 已经售罄 通知其他节点
            redisTemplate.convertAndSend("seckillpush", skuId + ":0");
            return;
        }
        //预下单
        OrderRecode orderRecode = new OrderRecode();
        orderRecode.setNum(1);
        orderRecode.setOrderStr(DigestUtils.md5DigestAsHex((userId + skuId).getBytes()));
        orderRecode.setSeckillGoods(this.getSeckillGoods(skuId));
        orderRecode.setUserId(userId);

        // 将预下单信息保存到redis中
//        redisTemplate.opsForHash().put(RedisConst.SECKILL_ORDERS, userId, skuId.toString());
        redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).put(userId, orderRecode);

        this.updateStockCount(skuId);
    }

    // 检查订单
    /*
    1.  判断用户是否在缓存中存在
    2.  判断用户是否抢单成功
    3.  判断用户是否下过订单
    4.  判断状态位
     */
    @Override
    public Result checkOrder(Long skuId, String userId) {
        // 判断用户是否在缓存中存在
        Boolean flag = redisTemplate.hasKey(RedisConst.SECKILL_USER + userId);
        if (flag) {
            // 判断用户是否抢单成功
            Boolean result = redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_ORDERS, userId);
            if (result) {
//                OrderRecode orderRecode = (OrderRecode) redisTemplate.opsForHash().get(RedisConst.SECKILL_ORDERS, userId);
                OrderRecode orderRecode = (OrderRecode) redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).get(userId);

                return Result.build(orderRecode, ResultCodeEnum.SECKILL_SUCCESS);
            }
        }

        // 判断用户是否下过单
        Boolean isSaveOrder = redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_ORDERS_USERS, userId);
        if (isSaveOrder) {
            // 下过单
            String orderId = (String) redisTemplate.opsForHash().get(RedisConst.SECKILL_ORDERS_USERS, userId);
            return Result.build(orderId, ResultCodeEnum.SECKILL_ORDER_SUCCESS);
        }

        // 判断状态位
        String status = (String) CacheHelper.get(skuId.toString());
        if ("0".equals(status)) {
            return Result.build(null, ResultCodeEnum.SECKILL_FAIL);
        }
        return Result.build(null, ResultCodeEnum.SECKILL_RUN);
    }

    // 更新库存
    @Transactional(rollbackFor = Exception.class)
    public void updateStockCount(Long skuId) {
        // 上锁
        ReentrantLock lock = new ReentrantLock();
        lock.lock();
        try {
            Long count = redisTemplate.opsForList().size(RedisConst.SECKILL_STOCK_PREFIX + skuId);
            if (count % 2 == 0) {
                SeckillGoods seckillGoods = this.getSeckillGoods(skuId);
                seckillGoods.setStockCount(count.intValue());
                seckillGoodsMapper.updateById(seckillGoods);
                redisTemplate.opsForHash().put(RedisConst.SECKILL_GOODS, seckillGoods.getSkuId().toString(), seckillGoods);
            }
        } catch (Exception e) {
            // 记录日志
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
